package puzzle.nurikabe.solver;

import java.util.List;
import java.util.Map;

import puzzle.common.data.HatanException;
import puzzle.common.point.Pnt;
import puzzle.common.solver.TopologicalRule;
import puzzle.nurikabe.data.NurikabeBoard;
import puzzle.nurikabe.data.ShimaState;

class ShimaEscapeRule implements TopologicalRule<NurikabeBoard, NurikabeTopology> {

	public boolean apply(NurikabeBoard b, NurikabeTopology topology) throws HatanException {
		boolean isChanged = false;
		for (Map.Entry<Integer, List<Pnt>> entry : topology.getShimaEscapePoints().entrySet()) {
			int n = entry.getKey();
			ShimaState s = b.getShimaState(n);

			if (s == null || s.getArea() < s.n) {
				List<Pnt> ps = entry.getValue();
				if (ps.size() == 0) {
					throw new HatanException();
				} else if (ps.size() == 1) {
					isChanged |= escape1(b, entry.getValue());
				} else if (ps.size() == 2) {
					if (s != null && s.n == 2) { // TODO
						isChanged |= escape2(b, entry.getValue());
					}
				}
			}
		}
		return isChanged;
	}

	private boolean escape1(NurikabeBoard b, List<Pnt> ps) throws HatanException {
		Pnt p = ps.get(0);
		return b.setShima(p.x, p.y);
	}

	private boolean escape2(NurikabeBoard b, List<Pnt> ps) throws HatanException {
		Pnt p1 = ps.get(0);
		Pnt p2 = ps.get(1);
		if (Math.abs(p1.x - p2.x) == 1 && Math.abs(p1.y - p2.y) == 1) {
			if (b.getBoardState(p1.x, p2.y) == 0) {
				return b.setKabe(p1.x, p2.y);
			} else if (b.getBoardState(p2.x, p1.y) == 0) {
				return b.setKabe(p2.x, p1.y);
			}
		}
		return false;
	}

}
